package com.zl.learning.thread;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class TestCondition {
    Lock lock = new ReentrantLock();
    Condition notFull = lock.newCondition();
    Condition notEmpty = lock.newCondition();
    private int size;

    List<String> blockQueue;

    public TestCondition(int size) {
        this.size = size;
        this.blockQueue = new ArrayList<>(size);
    }

    private void take() {
        lock.lock();
        try {
            while (blockQueue.isEmpty()) {
                notEmpty.await();
                System.out.println("=============== notEmpty =============");
            }
            System.out.println(blockQueue.get(0));
            blockQueue.remove(0);
            notFull.signal();
            size--;
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    private void put(String val) {
        lock.lock();
        try {
            while (size == blockQueue.size()) {
                notFull.await();
                System.out.println("=============== notFull =============");
            }
            blockQueue.add(val);
            size++;
            notEmpty.signal();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) {
        TestCondition testCondition = new TestCondition(10);
        new Thread(() -> {
            for (int i = 0; i < 20; i++) {
                for (int j = 0; j < 200; j++) {
                    testCondition.put("a:" + i + ":" + j);
                }
                try {
                    TimeUnit.SECONDS.sleep(3);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();

        new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                testCondition.take();
            }
        }).start();
    }
}
